package com.bridgeintelligent.tag.bulkload.service.core;

import com.bridgeintelligent.tag.bulkload.api.BulkLoadException;
import com.bridgeintelligent.tag.bulkload.api.FileExportDto;
import com.bridgeintelligent.tag.bulkload.api.LookLikeExportDto;
import com.bridgeintelligent.tag.bulkload.api.fileload.FileLoadModel;
import com.bridgeintelligent.tag.bulkload.api.fileload.FileLoadResult;
import com.bridgeintelligent.tag.bulkload.service.es.ESUtils;
import com.bridgeintelligent.tag.remotefile.RemoteFileHandler;
import com.wayneleo.quickstart.framework.ExceptionCode;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.common.Strings;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.springframework.stereotype.Service;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;


@Slf4j
@AllArgsConstructor
@Service
public class FileLoadLookLikeHandler {

    private static final String ALL_EXPORT = "0";

    private static final String SCORE = "score";

    private static final String CUSTNO = "cust_id";

    private static final String LOCAL_FILE_FORMAT = "/data/%s.txt";

    private static final String DIVIDE_SIGN = "|";

    private static final String FIRST_LINE = "客户号|评分值|";

    private static final String SUB_SIGN = "_";

    private RemoteFileHandler remoteFileHandler;

    private static final List LINK_LIST = new LinkedList();

    static {
        LINK_LIST.add(CUSTNO);
        LINK_LIST.add(SCORE);
    }

    public FileLoadResult handler(FileExportDto fileExportDto, LookLikeExportDto lookLikeConfig) {

        FileLoadModel fileLoadModel = createFileLoad(lookLikeConfig);
        File file = new File(String.format(LOCAL_FILE_FORMAT, fileExportDto.getId()));
        if (!file.exists()) {
            file.getParentFile().mkdir();
        }
        try (FileOutputStream fos = new FileOutputStream(file); BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(fos))) {
            bufferedWriter.write(FIRST_LINE);
            bufferedWriter.newLine();
            AtomicInteger num = new AtomicInteger();
            writeHandler(lookLikeConfig.getEsIndex(), fileLoadModel, num, bufferedWriter);
            bufferedWriter.close();
            return new FileLoadResult(num.get(), remoteFileHandler.uploadWhiteList(file.getAbsolutePath(), fileExportDto.getId()));
        } catch (Exception e) {
            log.error("写入本地文件出现异常", e);
            throw new BulkLoadException(new ExceptionCode(999, "写入本地文件出现异常"));
        }
    }

    private void writeHandler(String indexName, FileLoadModel fileLoadModel, AtomicInteger num,BufferedWriter bufferedWriter) {
        ESUtils.scrollSearch(indexName, fileLoadModel, hits -> {
            for (SearchHit hit : hits) {
                StringBuilder tmp = new StringBuilder();
                num.getAndIncrement();
                LINK_LIST.forEach(e->{
                    Object source = hit.getSourceAsMap().get(e);
                    String result = source == null ? SUB_SIGN : source.toString();
                    tmp.append(result).append(DIVIDE_SIGN);
                });
                bufferedWriter.write(tmp.toString());
                bufferedWriter.newLine();
            }
        });
    }

    private FileLoadModel createFileLoad(LookLikeExportDto lookLikeConfig) {
        FileLoadModel fileLoadModel = new FileLoadModel();
        //如果是全部数据导出
        QueryBuilder queryBuilder;
        if (lookLikeConfig.getExportType().equals(ALL_EXPORT)){
            queryBuilder = QueryBuilders.matchAllQuery();
        }else{
            String[] minMax = lookLikeConfig.getMinMax().split("-");
            if (!StringUtils.isEmpty(lookLikeConfig.getFlag()) && lookLikeConfig.getFlag().equals("∞")){
                queryBuilder = QueryBuilders.rangeQuery(SCORE).gte(Double.parseDouble(minMax[0]));
            }else{
                queryBuilder = QueryBuilders.boolQuery()
                        .must(QueryBuilders.rangeQuery(SCORE).gte(Double.parseDouble(minMax[0])))
                        .must(QueryBuilders.rangeQuery(SCORE).lt(Double.parseDouble(minMax[1])));
            }
        }
        fileLoadModel.setQueryBuilder(queryBuilder);
        fileLoadModel.setExcludes(Strings.EMPTY_ARRAY);
        fileLoadModel.setIncludes(new String[]{CUSTNO,SCORE});
        return fileLoadModel;
    }
}
